package org.zfin.properties.ant;

import org.apache.commons.configuration.ConfigurationException;
import org.apache.commons.configuration.PropertiesConfiguration;
import org.apache.log4j.Logger;

import java.util.*;

/**
 * By default commons configuration builds a list for duplicate key entries.
 * The resultant behavior is that the first entry can not be overridden by later entries, but that
 * is the default behavior for our properties.
 */
public class OverridePropertiesConfiguration extends PropertiesConfiguration{

    private final Logger logger = Logger.getLogger(OverridePropertiesConfiguration.class) ;
    private final String OVERRIDE_PREFIX = "override:" ;
    private boolean alwaysOverride = false ;

    public OverridePropertiesConfiguration(String propertyFilePath,boolean alwaysOverride) throws ConfigurationException{
        super() ;
        setIncludesAllowed(true);
        this.alwaysOverride = alwaysOverride ;
        setFileName(propertyFilePath);
        logger.debug(getFileName());
        load();
    }

    /**
     * @return An iterator to a sorted set of keys.
     */
    @Override
    public Iterator getKeys() {
        Set sortedSet = new TreeSet() ;
        for(Iterator oldIterator = super.getKeys(); oldIterator.hasNext() ; ){
            sortedSet.add(oldIterator.next()) ;
        }
        return sortedSet.iterator();
    }

    @Override
    protected void addPropertyDirect(String key, Object value) {

        if(alwaysOverride || value.toString().startsWith(OVERRIDE_PREFIX)){

            if(value.toString().startsWith(OVERRIDE_PREFIX)){
                value = value.toString().substring(OVERRIDE_PREFIX.length()) ;
            }

            Object previousValue = getProperty(key);

            if (previousValue == null)
            {
                super.addPropertyDirect(key,value);
            }
            else if (previousValue instanceof List)
            {
                // the value is added to the existing list
                ((List) previousValue).clear();
                ((List) previousValue).add(value);
            }
            else
            {
                clearPropertyDirect(key);
                super.addPropertyDirect(key,value);
            }
        }
        else{
            super.addPropertyDirect(key,value);
        }

    }
}
